/*
 * Copyright 2018 The Bazel Authors. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.idea.blaze.base.ideinfo;

import static com.google.common.truth.Truth.assertThat;

import com.google.devtools.intellij.aspect.Common;
import com.google.devtools.intellij.ideinfo.IntellijIdeInfo;
import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link AndroidIdeInfo}. */
@RunWith(JUnit4.class)
public class AndroidIdeInfoTest {

  /**
   * Verifies that we correctly interpret old-style protobufs (generated for CLs prior to
   * cl/215979760) that made use of the "resources" field rather than "resource_files". Such protos
   * will crop up when syncing a workspace to older CLs.
   */
  @Test
  public void resourceBackwardsCompatibilityTest() {
    IntellijIdeInfo.AndroidIdeInfo input =
        IntellijIdeInfo.AndroidIdeInfo.newBuilder()
            .addResources(sourceProto("com/google/mylib/res"))
            .addResources(sourceProto("com/google/anotherlib/res"))
            .build();

    AndroidIdeInfo output = AndroidIdeInfo.fromProto(input);

    assertThat(
            output.getResources().stream()
                .map(AndroidResFolder::getRoot)
                .map(ArtifactLocation::getRelativePath)
                .collect(Collectors.toList()))
        .containsExactly("com/google/mylib/res", "com/google/anotherlib/res");
  }

  /**
   * Verifies that we correctly interpret new-style protobufs (generated by the aspect after
   * cl/215979760) that use the "resource_files" attribute and also fill in the "resources"
   * attribute with the same roots.
   */
  @Test
  public void resourceFolderAndResourcesTest() {
    Common.ArtifactLocation myLibRoot = sourceProto("com/google/mylib/res");
    Common.ArtifactLocation anotherLibRoot = sourceProto("com/google/anotherlib/res");
    Common.ArtifactLocation resourceAar = sourceProto("com/google/mylib/resources.aar");

    IntellijIdeInfo.AndroidIdeInfo input =
        IntellijIdeInfo.AndroidIdeInfo.newBuilder()
            .addResources(myLibRoot)
            .addResources(anotherLibRoot)
            .addResFolders(
                IntellijIdeInfo.ResFolderLocation.newBuilder()
                    .setRoot(myLibRoot)
                    .setAar(resourceAar)
                    .build())
            .addResFolders(
                IntellijIdeInfo.ResFolderLocation.newBuilder().setRoot(anotherLibRoot).build())
            .build();

    AndroidIdeInfo output = AndroidIdeInfo.fromProto(input);

    assertThat(
            output.getResources().stream()
                .map(AndroidResFolder::getRoot)
                .map(ArtifactLocation::getRelativePath)
                .collect(Collectors.toList()))
        .containsExactly("com/google/mylib/res", "com/google/anotherlib/res");

    AndroidResFolder folder0 = output.getResources().get(0);
    AndroidResFolder folder1 = output.getResources().get(1);

    assertThat(folder0.getRoot()).isEqualTo(ArtifactLocation.fromProto(myLibRoot));
    assertThat(folder1.getRoot()).isEqualTo(ArtifactLocation.fromProto(anotherLibRoot));

    assertThat(folder0.getAar()).isEqualTo(ArtifactLocation.fromProto(resourceAar));
  }

  /**
   * Verifies that we can handle forwards-compatibility to a future version of the aspect that no
   * longer fills in the "resources" field and only supplies "resFolders". This is what the proto
   * will probably resemble after we drop support for blaze plugin versions that require the
   * "resources" field.
   */
  @Test
  public void resourceFolderWithoutResourcesTest() {
    Common.ArtifactLocation myLibRoot = sourceProto("com/google/mylib/res");
    Common.ArtifactLocation anotherLibRoot = sourceProto("com/google/anotherlib/res");
    Common.ArtifactLocation resourceAar = sourceProto("com/google/mylib/resources.aar");

    IntellijIdeInfo.AndroidIdeInfo input =
        IntellijIdeInfo.AndroidIdeInfo.newBuilder()
            .addResFolders(
                IntellijIdeInfo.ResFolderLocation.newBuilder()
                    .setRoot(myLibRoot)
                    .setAar(resourceAar)
                    .build())
            .addResFolders(
                IntellijIdeInfo.ResFolderLocation.newBuilder().setRoot(anotherLibRoot).build())
            .build();

    AndroidIdeInfo output = AndroidIdeInfo.fromProto(input);

    assertThat(
            output.getResources().stream()
                .map(AndroidResFolder::getRoot)
                .map(ArtifactLocation::getRelativePath)
                .collect(Collectors.toList()))
        .containsExactly("com/google/mylib/res", "com/google/anotherlib/res");

    AndroidResFolder folder0 = output.getResources().get(0);
    AndroidResFolder folder1 = output.getResources().get(1);

    assertThat(folder0.getRoot()).isEqualTo(ArtifactLocation.fromProto(myLibRoot));
    assertThat(folder1.getRoot()).isEqualTo(ArtifactLocation.fromProto(anotherLibRoot));

    assertThat(folder0.getAar()).isEqualTo(ArtifactLocation.fromProto(resourceAar));
  }

  private static Common.ArtifactLocation sourceProto(String location) {
    return Common.ArtifactLocation.newBuilder().setRelativePath(location).setIsSource(true).build();
  }
}
